import json
from datetime import datetime, time, timedelta

import pytz
from rest_framework import serializers

from Group.models import MemberTraining, TeamMemberShip, MemberTrainingRecord
from Group.util import TrainStatus


class TeamMemberRemarkSerializer(serializers.ModelSerializer):
    class Meta:
        model = TeamMemberShip
        fields = (
            'id',
            'name',
        )


class TrainMemberListSerializer(serializers.ModelSerializer):
    avatar = serializers.SerializerMethodField(read_only=True)
    name = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = TeamMemberShip
        fields = (
            'id',
            'name',
            'avatar'
        )

    def get_avatar(self, obj):
        try:
            url = obj.person.detail.profile_picture.url
        except:
            url = ""
        return url

    def get_name(self, obj):
        if obj.name is None:
            return obj.person.username
        return obj.name


class TeamMemberTrainSerializer(serializers.ModelSerializer):
    member = TrainMemberListSerializer(read_only=True)
    status = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = MemberTraining
        fields = (
            'id',
            'name',
            'member',
            'status',
        )

    def get_status(self, obj):
        existing_record = MemberTrainingRecord.objects.filter(
            training=obj,
            create_time__date=datetime.now().date(),
            record_type__in=[TrainStatus.REGISTERED, TrainStatus.LEAVE]  # 已签到或请假
        )
        if existing_record.exists():
            return existing_record.first().record_type
        elif MemberTrainingRecord.objects.filter(
                training=obj,
                create_time__date=datetime.now().date(),
                record_type__in=[TrainStatus.ABSENCE]  # 已签到或请假
        ).exists():
            return TrainStatus.ABSENCE
        return TrainStatus.UNKNOWN


class TeamMemberSelfTrainViewSerializer(serializers.ModelSerializer):
    status = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = MemberTraining
        fields = (
            'id',
            'team',
            'member',
            'name',
            'training_type',
            'start_time',
            'end_time',
            'recurrence_days',
            'status',
        )

    def get_status(self, obj):
        existing_record = MemberTrainingRecord.objects.filter(
            training=obj,
            create_time__date=datetime.now().date(),
            record_type__in=[TrainStatus.REGISTERED, TrainStatus.LEAVE]  # 已签到或请假
        )
        if existing_record.exists():
            return existing_record.first().record_type
        return TrainStatus.UNKNOWN

    def validate(self, data):
        training_type = data.get('training_type')
        if training_type == 0:
            if data.get('recurrence_days') is None:
                raise serializers.ValidationError("定期训练必须指定每周训练日期")
            try:
                recurrence_days = json.loads(data.get('recurrence_days'))
            except:
                raise serializers.ValidationError("每周训练日期格式错误")
            if type(recurrence_days) is not list:
                raise serializers.ValidationError("每周训练日期格式错误")
            for day in recurrence_days:
                if day < 1 or day > 7:
                    raise serializers.ValidationError("每周训练日期格式错误")
            if len(set(recurrence_days)) != len(recurrence_days):
                raise serializers.ValidationError("每周训练日期重复")
        elif training_type == 1 and data.get('recurrence_days') is not None:
            raise serializers.ValidationError("单次训练不能指定每周训练日期")

        # 训练开始和结束时间不得早于早上六点，结束时间不得晚于晚上11点30分
        start_time = data.get('start_time')
        end_time = data.get('end_time')
        six_am = time(6, 0)
        eleven_thirty_pm = time(23, 30)

        if end_time <= start_time:
            raise serializers.ValidationError("结束时间不能早于开始时间")

        if start_time.time() < six_am or end_time.time() > eleven_thirty_pm:
            raise serializers.ValidationError("训练时间应在早上6点到晚上11点30分之间")

        # 单次训练，开始时间和结束时间必须在同一天
        if data['training_type'] == 1:
            if start_time.date() != end_time.date():
                raise serializers.ValidationError("单次训练的开始时间和结束时间必须在同一天")
            # 每天训练时间不得超过10个小时
            if end_time - start_time > timedelta(hours=10):
                raise serializers.ValidationError("单次训练时间不得超过10个小时")
        else:
            start_dt = datetime.combine(datetime.min, start_time.time())
            end_dt = datetime.combine(datetime.min, end_time.time())
            if start_dt >= end_dt:
                raise serializers.ValidationError("开始时间不能晚于结束时间")
            if (end_dt - start_dt) > timedelta(hours=10):
                raise serializers.ValidationError("每天训练时间不得超过10个小时")

        return data


"""
    获取用户今日训练状态的序列化器
"""


class TeamMemberSignInSerializer(serializers.ModelSerializer):
    class Meta:
        model = MemberTrainingRecord
        fields = ['member', 'training', 'record_type']

    def validate(self, data):
        training = data.get('training')
        member = data.get('member')

        # 检查训练是否属于该成员
        if not MemberTraining.objects.filter(id=training.id, member=member).exists():
            raise serializers.ValidationError("该训练不属于当前用户")

        # 获取当前时间和日期
        now = datetime.now(pytz.timezone('Asia/Shanghai'))
        today = now.date()

        # 检查是否为签到请求
        if data['record_type'] == 1:  # 签到请求
            # 检查用户是否已经签到
            if MemberTrainingRecord.objects.filter(
                    member=member,
                    training=training,
                    create_time__date=today,
                    record_type=TrainStatus.REGISTERED  # 签到记录
            ).exists():
                raise serializers.ValidationError("您今天已经签到了")
            if MemberTrainingRecord.objects.filter(
                    member=member,
                    training=training,
                    create_time__date=today,
                    record_type=TrainStatus.LEAVE  # 签到记录
            ).exists():
                raise serializers.ValidationError("您今天已经请假了")

            # 检查当前时间是否在训练时间范围内
            if training.training_type == 0:  # 定期训练
                recurrence_days = json.loads(training.recurrence_days)
                if today.weekday() + 1 not in recurrence_days:
                    raise serializers.ValidationError("今天没有该训练任务")
                # 检查时间部分
                start_time_aware = training.start_time.astimezone(pytz.timezone('Asia/Shanghai')).time()
                end_time_aware = training.end_time.astimezone(pytz.timezone('Asia/Shanghai')).time()
                if not (start_time_aware <= now.time() <= end_time_aware):
                    raise serializers.ValidationError("当前时间不在训练时间范围内")
            elif training.training_type == 1:  # 单次训练
                if today != training.start_time.date():
                    raise serializers.ValidationError("该训练不在今天")
                start_time_aware = training.start_time.astimezone(pytz.timezone('Asia/Shanghai'))
                end_time_aware = training.end_time.astimezone(pytz.timezone('Asia/Shanghai'))
                if not (start_time_aware <= now <= end_time_aware):
                    raise serializers.ValidationError("当前时间不在训练时间范围内")
            data['remark'] = f"签到成功，时间:{now.strftime('%Y-%m-%d %H:%M:%S')}"
        else:
            if MemberTrainingRecord.objects.filter(
                    member=member,
                    training=training,
                    record_type=TrainStatus.LEAVE  # 签到记录
            ).exists():
                raise serializers.ValidationError("您今天已经请假了")
            data['remark'] = f"请假成功，时间:{now.strftime('%Y-%m-%d %H:%M:%S')}"

        return data
